﻿
Imports std
Imports runrroom

Public Class config
    Public Shared reserveJobInfoSeconds As Int64 = configNaming.defaultValue.distrrun.reserveJobInfoSeconds
    Public Shared uploadJobInfoStoroom As String = configNaming.defaultValue.distrrun.uploadJobInfoStoroom
    Public Shared uploadJobInfoStoroomAddress As IPEndPoint2 = IPEndPoint2.create(uploadJobInfoStoroom)
End Class

Public Module distrrun
    Public Const defaultConfigfile As String = "distrrun.ini"
    Public Const jobinfoStoroomKey As String = runrroom.defaultValue.jobinfoHistoryStoroomKey
    Public Event configChanged()
    Private _jobmgr As jobmgr_t = Nothing
    Private _jobuploader As jobuploader_t = Nothing
    Private _distrrule_map As distrrule_map = Nothing
    Private server As drserver = Nothing
    Private WithEvents cm As configMonitor = Nothing

    Public Function jobmgr() As jobmgr_t
        assert(Not _jobmgr Is Nothing)
        Return _jobmgr
    End Function

    Public Function jobuploader() As jobuploader_t
        assert(Not _jobuploader Is Nothing)
        Return _jobuploader
    End Function

    Public Function distrrule_map() As distrrule_map
        assert(Not _distrrule_map Is Nothing)
        Return _distrrule_map
    End Function

    Private Sub initial()
        config.reserveJobInfoSeconds = cm.parameter(configNaming.distrrun.section, _
                                                    configNaming.distrrun.reserveJobInfoSeconds, _
                                                    configNaming.defaultValue.distrrun.reserveJobInfoSeconds)
        config.uploadJobInfoStoroom = cm.parameter(configNaming.distrrun.section, _
                                                   configNaming.distrrun.uploadJobInfoStoroom, _
                                                   configNaming.defaultValue.distrrun.uploadJobInfoStoroom)
        Dim address As IPEndPoint2 = Nothing
        If Not IPEndPoint2.parse(config.uploadJobInfoStoroom, address) Then
            raiseError("cannot parse uploadJobInfoStoroom as ipaddress, " + config.uploadJobInfoStoroom, _
                       errorHandle.errorType.user)
        Else
            config.uploadJobInfoStoroomAddress = address
        End If

        Dim ns As vector(Of String) = Nothing
        Dim rs As vector(Of String) = Nothing
        If cm.readlist(configNaming.distrrun.section, configNaming.distrrun.distrruleName, ns) AndAlso _
           cm.readlist(configNaming.distrrun.section, configNaming.distrrun.distrrule, rs) Then
            If ns.size() <> rs.size() Then
                raiseError("distrrule count is not matching distrruleName.", errorHandle.errorType.user)
            End If
            Dim dm As distrrule_map = Nothing
            dm = New distrrule_map()
            For i As Int64 = 0 To min(ns.size(), rs.size()) - 1
                If dm.insert(ns(i), rs(i)) = dm.end() Then
                    raiseError("cannot insert distrrule " + ns(i) + ", " + rs(i), errorHandle.errorType.user)
                End If
            Next

            Threading.Interlocked.Exchange(_distrrule_map, dm)
        Else
            raiseError("no internal distrrule found in configuration.", errorHandle.errorType.warning)
        End If
        RaiseEvent configChanged()
    End Sub

    Private Sub startservice()
        assert(_jobmgr Is Nothing)
        _jobmgr = New jobmgr_t()
        assert(_jobuploader Is Nothing)
        _jobuploader = New jobuploader_t()
        assert(server Is Nothing)
        server = New drserver()
        server.start()
    End Sub

    Private Sub shutdownservice()
        server.stop()
        jobuploader().close()
    End Sub

    Private Sub monitor()
        registerConsoleExtHandle()

        While Not consoleExtSignal()
            If server.health() Then
                sleep(1000)
            Else
                Exit While
            End If
        End While

        If Not consoleExtSignal() Then
            If Not server.health() Then
                raiseError("server engender an error, start shutdown.", errorHandle.errorType.exclamation)
            End If
        Else
            raiseError("terminating signal caught, start shutdown.")
        End If
    End Sub

    Private Sub unhandledException(ByVal e As Exception)
        shutdownservice()
    End Sub

    Public Sub main(ByVal args() As String)
        dpslib.consoleApplicationStartParameters.unhandledExceptionhandler = AddressOf unhandledException
        dpslib.startmain()
        Dim configfile As String = Nothing
        If args.Length() = 0 Then
            configfile = defaultConfigfile
        Else
            configfile = args(0)
        End If
        cm = New configMonitor()
        assert(cm.open(configfile))
        initial()

        startservice()
        monitor()
        shutdownservice()
        finishmain()
    End Sub

    Private Sub cm_configChanged() Handles cm.configChanged
        initial()
    End Sub
End Module
